package com.lu.utils;

import com.alibaba.fastjson.JSONObject;
import com.lu.constants.EsConstant;
import com.lu.exception.EsModularException;
import com.lu.model.EsUpdaeBatchDocAction;
import com.lu.model.EsUpdaeDocAction;
import io.searchbox.action.Action;
import io.searchbox.action.BulkableAction;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.Bulk;
import io.searchbox.core.Delete;
import io.searchbox.core.Index;
import io.searchbox.core.Update;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @program Elasticsearch
 * @description: es jest 对doc增删改 工具
 * @author: zhanglu
 * @create: 2020-04-30 08:50:00
 */
@Setter
@Slf4j
@Component
public class JestUpdateDocUtil {

    @Autowired
    private JestClient jestClient;

    /******************************************增删改******************************************/

    /**
     * 单文档 新增
     * @param indexName
     * @param typeName
     * @param obj       文档对象
     * @return          返回索引id
     * @throws Exception
     */
    public EsUpdaeDocAction insert(String indexName, String typeName, Object obj) {
        Index index = new Index.Builder(obj).index(indexName).type(typeName).build();
        return updateActionHandle(index);
    }

    /**
     * 单文档 新增
     * @param indexName
     * @param typeName
     * @param obj       文档对象
     * @return          返回索引id
     * @throws Exception
     */
    public EsUpdaeDocAction insert(String indexName, String typeName, String id, Object obj) {
        Index index = new Index.Builder(obj).index(indexName).type(typeName).id(id).build();
        return updateActionHandle(index);
    }

    /**
     * 批量插入文档
     * @param indexName
     * @param typeName
     * @param objs      文档列表
     * @throws Exception
     */
    public EsUpdaeBatchDocAction insertBatch(String indexName, String typeName, List<?> objs) {
        List<Index> indexList = new ArrayList<>();
        objs.stream().forEach(o -> {
            indexList.add(new Index.Builder(o).build());
        });
        return updateBatchActionHandle(indexName, typeName, indexList);
    }

    /**
     * 单文档 更新，全量覆盖
     * @param indexName
     * @param typeName
     * @param obj       文档对象
     * @return          返回索引id
     * @throws Exception
     */
    public EsUpdaeDocAction updateCover(String indexName, String typeName, String id, Object obj) {
        Index index = new Index.Builder(obj).index(indexName).type(typeName).id(id).build();
        return updateActionHandle(index);
    }

    /**
     * 单文档更新，按值更新，即 null 值不会更新，注意，传入的实体，最好都是引用类型，例如 long view，若不设值，默认值是0，就会与预期不符
     * @param indexName
     * @param typeName
     * @param id
     * @param obj
     * @return
     */
    public EsUpdaeDocAction update(String indexName, String typeName, String id, Object obj) {
        //按值更新，需要在本身对象之外，包装一层
        Map<String, Object> objMap = new HashMap<>(2);
        objMap.put(EsConstant.DOC, obj);
        Update update = new Update.Builder(objMap).index(indexName).type(typeName).id(id).build();
        return updateActionHandle(update);
    }

    /**
     * 删除单个文档
     * @param indexName
     * @param typeName
     * @param id
     * @return
     * @throws Exception
     */
    public EsUpdaeDocAction delete(String indexName, String typeName, String id) {
        Delete delete = new Delete.Builder(id).index(indexName).type(typeName).build();
        return updateActionHandle(delete);
    }

    /**
     *
     * @param indexName
     * @param typeName
     * @param ids
     * @return
     * @throws Exception
     */
    public EsUpdaeBatchDocAction deleteBatch(String indexName, String typeName, List<String> ids) {
        List<Delete> deleteList = new ArrayList<>();
        ids.stream().forEach(id -> {
            deleteList.add(new Delete.Builder(id).build());
        });
       return updateBatchActionHandle(indexName, typeName, deleteList);
    }

    /******************************************其他******************************************/

    /**
     * 断言 操作是否成功，本工具类的逻辑，增删改，批量，失败的话，返回null
     * @param obj
     * @param errorMsg
     * @throws EsModularException
     */
    public void assertIsOpSuccess(Object obj, String errorMsg) throws EsModularException {
        if(obj == null){
            throw new EsModularException(errorMsg);
        }
    }

    /**
     * 断言 操作是否成功，本工具类的逻辑，增删改，批量，失败的话，返回null
     * @param obj
     * @param errorMsg
     * @throws EsModularException
     */
    public void assertIsOpSuccess(Object obj, String errorMsg, Consumer consumer) throws EsModularException{
        if(obj == null){
            consumer.accept(null);
            throw new EsModularException(errorMsg);
        }
    }

    /**
     * 更新操作，处理
     * @param action
     * @return
     * @throws Exception
     */
    public EsUpdaeDocAction updateActionHandle(Action action) {
        EsUpdaeDocAction esUpdaeDocAction = null;
        try {
            JestResult jestResult = jestClient.execute(action);
            if(!jestResult.isSucceeded()){
                return null;
            }
            esUpdaeDocAction = JSONObject.parseObject(jestResult.getJsonString(), EsUpdaeDocAction.class);
        } catch (IOException e) {
            log.error("JestUpdateDocUtil-updateActionHandle异常:", e);
        }
        return esUpdaeDocAction;
    }

    /**
     * 批量更新操作，处理
     * @return
     * @throws Exception
     */
    public EsUpdaeBatchDocAction updateBatchActionHandle(String indexName, String typeName, List<? extends BulkableAction> actionList) {
        EsUpdaeBatchDocAction esUpdaeBatchDocAction = null;
        try {
            Bulk bulk = new Bulk.Builder()
                    .defaultIndex(indexName)
                    .defaultType(typeName)
                    .addAction(actionList).build();
            JestResult jestResult = jestClient.execute(bulk);
            if(!jestResult.isSucceeded()){
                return null;
            }
            esUpdaeBatchDocAction = JSONObject.parseObject(jestResult.getJsonString(), EsUpdaeBatchDocAction.class);
        } catch (IOException e) {
            log.error("JestUpdateDocUtil-updateBatchActionHandle异常:", e);
        }
        return esUpdaeBatchDocAction;
    }

}
